package com.gitee.ywj1352.server.service;

import com.gitee.ywj1352.common.YWJFrameDecoder;
import com.gitee.ywj1352.common.YWJFrameEncoder;
import com.gitee.ywj1352.server.ObjectDecoder;
import com.gitee.ywj1352.server.ObjectEncoder;
import com.gitee.ywj1352.server.ServerFactory;
import com.gitee.ywj1352.server.handler.ServerProcessHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.UnorderedThreadPoolEventExecutor;

public class NettyServerService {

    public void start(int port, ServerFactory serverFactory) throws InterruptedException {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.channel(NioServerSocketChannel.class);
        serverBootstrap.option(NioChannelOption.SO_BACKLOG, 1024);
        serverBootstrap.childOption(NioChannelOption.TCP_NODELAY, true);
        serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
        //thread
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("boss"));
        NioEventLoopGroup workGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("worker"));
        UnorderedThreadPoolEventExecutor businessGroup = new UnorderedThreadPoolEventExecutor(10, new DefaultThreadFactory("business"));
        serverBootstrap.group(bossGroup, workGroup);
        serverBootstrap.childHandler(new ChannelInitializer<NioSocketChannel>() {
            @Override
            protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                ChannelPipeline pipeline = nioSocketChannel.pipeline();
                pipeline.addLast("frameDecoder", new YWJFrameDecoder());
                pipeline.addLast("frameEncoder", new YWJFrameEncoder());
                pipeline.addLast("protocolDecoder", new ObjectDecoder());
                pipeline.addLast("protocolEncoder", new ObjectEncoder());
                // 业务执行模块
                pipeline.addLast(businessGroup, new ServerProcessHandler(serverFactory));
            }
        });
        ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
    }
}
